<?php
/*
route rules r1
$route['*']['/captcha'] = array('image', 'captcha');

route rules r2
$route['*']['/'] = 'index:index'
$route['*']['/project/&type{ktv}^([a-zA-Z]+)$.html'] = 'index:show'
$route['*']['/captcha'] = 'image:capthca';
第二套route规则条件：
1、以/分割每个节点
2、包含&开头的[a-zA-Z]{1}[a-zA-Z0-9]+为传入参数名称定义，此处不用正则获取，截取字符串的方法
3、以^$包含的部分为正则表达式匹配,没有的则应用通用规则
4、*子数组的为任意方法访问
5、指定方式为“模块：方法：其他”，其他可能使用base auth或者使用跳转的方式
6、default数组为默认模块和方法定义
7、除了“*”数组之外，可使用“get”、“post”方法来定义数组通用方法
8、
 */


define ( 'ROUTE_METHOD_REDIRECT', 'ROUTE_METHOD_REDIRECT' );
define ( 'ROUTE_METHOD_AUTH', 'ROUTE_METHOD_AUTH' );

class Route {
	

	private $param;
	private $config_route;	
	private $uristring;
	private $uri;
	private $filepath;
	
	const VAR_PREFIX = '&';				//Get variable prefix from sub
	const PATTERN_PREFIX = '^';			//Regular pattern prefix in sub
	const PATTERN_SUFFIX = '$';			//Regular pattern suffix in sub
	const VAR_DEFAULT_PREFIX = '{';		//Default variable prefix
	const VAR_DEFAULT_SUFFIX = '}';		//Default variable suffix
	
	public function __construct($config_route = array()) {
		if (DEBUG === TRUE) {
			echo '--- Route construct!' . '<br/>';
		}
		$this->config_route = $config_route;
		$this->doUri ();
		$this->parseUri ();
	}
	
	public function doUri() {
		$script_name = strtolower ( $_SERVER ['SCRIPT_NAME'] );
		$this->filepath = strrchr ( $script_name, '/' );
		$this->basepath = str_replace ( $this->filepath, '', $script_name );
		@list ( $requesturi, $suffix ) = explode ( "?", $_SERVER ["REQUEST_URI"] );
		$this->uristring = str_replace ( $this->filepath, '', strtolower ( $requesturi ) );
		$this->uri = str_replace ( $this->basepath, '', $this->uristring );
		if (DEBUG === TRUE) {
			echo '<h3>Route Info:</h3>';
			echo ' baseuri:' . $this->basepath . '<br />';
			echo ' uristring:' . $this->uristring . '<br />';
			echo ' uri:' . $this->uri . '<br />';
		}
	}
	
	public function parseUri() {
		$route = $this->config_route;
		if ($this->uri == '/' || $this->uri == $this->basepath) {
			//echo "<h1>No Route!</h1>";
			@$_GET ['MODULE'] = $this->param ['module'] = $_GET ['module'];
			@$_GET ['ACTION'] = $this->param ['action'] = $_GET ['action'];
		} elseif (ROUTE_ON === TRUE) {
			if (isset ( $route ['default'] )) {
				//echo "<h1>Route Default</h1>";
				$path = preg_replace ( array_keys ( $route ['default'] ), array_values ( $route ['default'] ), $this->uri );
				$param = explode ( "/", $path );
				@$_GET ['MODULE'] = $this->param ['module'] = $param [1];
				@$_GET ['ACTION'] = $this->param ['action'] = $param [2];
				if (count ( $param ) > 3) {
					for($i = 3; $i < count ( $param ); $i ++) {
						if ($param [$i] == '')
							@$_GET [$param [$i]] = $this->param [$param [$i]] = $param [++ $i];
					}
				}
				unset ( $route ['default'] );
			}
			if (! empty ( $route )) {
				//echo "<h1>Route!!!</h1>";
				$route_data = $this->parseRoute ( $this->uri );
				if (! empty ( $route_data )) {
					isset ( $route_data [0] ) && $route_data [0] != '' && @$_GET ['MODULE'] = $this->param ['module'] = $route_data [0];
					isset ( $route_data [1] ) && $route_data [1] != '' && @$_GET ['ACTION'] = $this->param ['action'] = $route_data [1];
				}
			}
		}
	}
	
	public function parseRoute($uri) {
		$type = strtolower ( $_SERVER ['REQUEST_METHOD'] );
		$route = $this->config_route;
		
		if (isset ( $route [$type] )) {
			$approute = $route [$type];
		}
		
		if (isset ( $route ['*'] )) {
			if (isset ( $approute ))
				$approute = array_merge ( $approute, $route ['*'] );
			else
				$approute = $route ['*'];
		}
		$match = NULL;
		if (isset ( $route ['*'] [$uri] ) && ! empty ( $route ['*'] [$uri] )) {
			$match = $route ['*'] [$uri];
		}
		
		if ($match != NULL) {
			return $match;
		} else {
			$uri = substr ( $uri, 1 );
			$uri_unit = explode ( '/', $uri );
			
			foreach ( $approute as $rkey => $rdata ) {
				$rkey = substr ( $rkey, 1 );
				$r_unit = explode ( '/', $rkey );
				if (sizeof ( $uri_unit ) !== sizeof ( $r_unit ))
					continue;
				
				if ($r_unit [0] !== $uri_unit [0])
					continue;
				
				$static_part = explode ( '/&', $rkey, 2 );
				$static_part = $static_part [0];
				
				if (substr ( $uri, 0, strlen ( $static_part ) ) !== $static_part)
					continue;
				
				$this->parseParam ( $r_unit, $uri_unit );
				
				return $rdata;
			}
		}
	}
	
	protected function parseParam($r_unit, $uri_unit) {
		$params = NULL;
		for($i = 0; $i < sizeof ( $r_unit ); $i ++) {
			$param_key = $r_unit [$i];
			if (strpos ( $param_key, '&' ) === 0) {
				$param_key = str_replace ( '&', '', $param_key );
				$params [$param_key] = $uri_unit [$i];
				$_GET [$param_key] = $uri_unit [$i];
			}
		}
		return $params;
	}

}
?>